/**
 * 单例管理辅助组件
 */
export class Instance {
  // 单例模式辅助组件
  private static _instance?: Instance;

  /**
   * 利用 map 存储所有的 instance
   */
  private maps: Map<string, any>;

  private constructor() {
    this.maps = new Map<string, any>();
  }

  /**
   * 获取单例模型
   * @constructor
   */
  public static Instance(): Instance {
    if (!Instance._instance) {
      Instance._instance = new Instance();
    }
    return Instance._instance;
  }

  /**
   * 获取指定单例
   * @param name 单例名称
   */
  public get<T>(name: string): T | null {
    if (this.maps.has(name)) {
      return this.maps.get(name) as T;
    }
    return null;
  }

  /**
   * 设置单例
   * @param name 名称
   * @param i 实例
   */
  public set<T>(name: string, i: T): void {
    if (this.maps.has(name)) {
      throw new Error(`name:${name} 重复了`);
    } else {
      this.maps.set(name, i);
    }
  }

  /**
   * 删除单例对象
   * 为了特殊情况需要删除单例时
   * @param name 单例名称
   */
  public remove(name: string): void {
    if (this.maps.has(name)) {
      this.maps.delete(name);
    }
  }

  /**
   * 获取或设置单例
   * 当单例存在时直接返回传入值
   * @param name 名称
   * @param i 实例
   */
  public getOrSet<T>(name: string, i: T): T {
    if (!this.maps.has(name)) {
      this.set<T>(name, i);
    }
    return i;
  }

  /**
   * 获取或设置单例
   * 当单例存在时直接返回
   * 当单例不存在时调用函数生成对象并存储
   * @param name 名称
   * @param func 生成函数
   */
  public getOrSetFunc<T>(name: string, func: () => T): T {
    if (!this.maps.has(name)) {
      this.set<T>(name, func());
    }
    return this.get<T>(name)!;
  }
}
